#include <loader.h>
#include <i386.h>
#include <mm.h>
#include <tipos.h>
#include <syscalls.h>
#include <serial.h>
#include <device.h>
#include <debug.h>
#include <con.h>
#include <fs.h>
#include <string.h>
#include <vga.h>
#include <hdd.h>


int __getpid(int a, void *b){
	(void) a;
	(void) b;
	return current_pid;
}

void* __palloc(int a, void *b){
	void *res;
	(void) a;
	(void) b;
	cli();
	res = palloc();
	sti();
	return res;
}

int __pipe(int ret, void *b) {
	return fs_pipe_open((int *) ret); 
}

void __exit(int ret, void *b){
	(void) b;
	cli();
	loader_exit();
	sti();
}

int __fork(int ret, void *b){
	cli();
	return loader_fork();
}

int __open(int ret, void *b){
	cli();
	return open(b, ret);
}

int __write(int ret, void *b){
	cli();

	sized_buffer *buf;
	buf = (sized_buffer *) b;

	return write(ret, buf->buffer, buf->size);
}

int __seek(int ret, void *b){
	cli();

	return seek(ret, (int) b);
}

int __read(int ret, void *b){
	cli();

	sized_buffer *buf;
	buf = (sized_buffer *) b;

	return read(ret, buf->buffer, buf->size);
}

int __flush(int ret, void *b){
	cli();

	return flush(ret);
}

void* __open_serial0(int ret, void *b){
	cli();
	return serial_open(0);
}

void* __open_con(int ret, void *b){
	cli();
	return con_open();
}

int 
__run(int pl, void * arch)
{

	chardev * cd = fs_open(arch, FS_OPEN_RDONLY);

	if (cd == NULL) 
		return 0;

	pso_file * ps = mm_mem_kalloc();

	int pid = 0;

	if (ps == NULL) 
		return 0;
	
	cd->read(cd, ps, sizeof(pso_file));
	
	if ( strncmp( (char*) ps->signature, "PSO", 4) != 0) {
		return 0;
	}
	
	int task_size = ps->mem_end_disk - ps->mem_start - sizeof(pso_file);

	cd->read(cd, ps + 1, task_size);
	
	pid = loader_load(ps, pl);

	mm_mem_free(ps);
	
	cd->flush(cd);
	
	return pid;
}

extern sint_32 hdd_block_read(blockdev *this, uint_32 pos, void *buf, uint_32 count);

int __hdd_test(int disk, void *buf) {

	//breakpoint();
	blockdev *hd = hdd_open(disk);
	//breakpoint();

	if(!hd) return 1;

	return hdd_block_read(hd, 0, buf, 1);

}

int __share_page(int a, void * addr)
{
	return mm_share_page( addr );
}

syscall_prototype syscall_table[SYSCALL_MAX] = {
		(syscall_prototype) __exit,
		(syscall_prototype) __getpid,
		(syscall_prototype) __palloc,
		(syscall_prototype) __open,
		(syscall_prototype) __read,
		(syscall_prototype) __write,
		(syscall_prototype) __flush,
		//(syscall_prototype) __open_serial0,
		//(syscall_prototype) __open_con,
		(syscall_prototype) __run,
		(syscall_prototype) __hdd_test,
		(syscall_prototype) __fork, 
		(syscall_prototype) __pipe,
		(syscall_prototype) __share_page,
		(syscall_prototype) __seek
};

uint_32 syscall_max = SYSCALL_MAX;;

